package ec.app.robocup;

import java.util.Arrays;

import sceneInfo.FuzzyFramework;
import sceneInfo.FuzzySceneLib;

import ec.*;
import ec.simple.*;
import ec.vector.*;

public class RobocupEvolutionDistance extends Problem implements SimpleProblemForm
    {
	FuzzySceneLib library1,library2,library3,library4;
	int sizedist=5;
	int sizeang=1;
	public static final int ANGLEPARAMETER = 0;
	
	public RobocupEvolutionDistance(){
		super();
		String LogFile1 = "A1_9.lsf";
		String LogFile2 = "NKAS-Attack4.lsf";
		String LogFile3 = "Poland_4.lsf";
		String LogFile4 = "Portugal_2.lsf";
       library1 = new FuzzySceneLib(LogFile1);
       library2 = new FuzzySceneLib(LogFile2);
       library3 = new FuzzySceneLib(LogFile3);
       library4 = new FuzzySceneLib(LogFile4);
	}
	
    public void evaluate(final EvolutionState state, final Individual ind, final int subpopulation, final int threadnum)
        {
        if (ind.evaluated) return;

        if (!(ind instanceof FloatVectorIndividual))
            state.output.fatal("Whoa!  It's not a FloatVectorIndividual!!!",null);
        
        FloatVectorIndividual ind2 = (FloatVectorIndividual)ind;
        
        float rawfitness = 0;
        
        // get angle parameters
        float [] angleparameters = new float [sizeang];
        
        for(int x=0; x<sizeang; x++){
        
        	angleparameters[x] = ANGLEPARAMETER;//ind2.genome[x];
        	
        }
        //get distance parameters
        float [] distparameters = new float [sizedist];

        for(int x=0; x<sizedist; x++){
        	if(ind2.genome[x]>0 ){
        	distparameters[x] = ind2.genome[x];
        	} else {
        		if (!(ind2.fitness instanceof SimpleFitness))
                    state.output.fatal("Whoa!  It's not a SimpleFitness!!!",null);
                ((SimpleFitness)ind2.fitness).setFitness(state,0, false); // sets fitness to 0 and quits
                ind2.evaluated = true;
        		return;
        	}
        }

       
        Arrays.sort(distparameters);
        //Arrays.sort(angleparameters);
        
        
        FuzzyFramework ff= new FuzzyFramework(angleparameters,distparameters, false);

        library1.setFramework(ff);
        library1.discretizeThis(ff);
        
        library2.setFramework(ff);
        library2.discretizeThis(ff);
   
        library3.setFramework(ff);
        library3.discretizeThis(ff);
        
        library4.setFramework(ff);
        library4.discretizeThis(ff);
   
        
        boolean ideal=false;
        
        float indistinguishablesRate1 = library1.evaluateConfusion();
        float indistinguishablesRate2 = library2.evaluateConfusion();
        float indistinguishablesRate3 = library3.evaluateConfusion();
        float indistinguishablesRate4 = library4.evaluateConfusion();
        
        //this gives us a rate between 0 and 1
        if (indistinguishablesRate1 == 0 && indistinguishablesRate2 == 0 && 
        	indistinguishablesRate3 == 0 ){
        	ideal = true;
        } 
        
        float raw1 = Math.max(1000  - (1000*indistinguishablesRate1), 0);
        float raw2 = Math.max(1000  - (1000*indistinguishablesRate2), 0);
        float raw3 = Math.max(1000  - (1000*indistinguishablesRate3), 0);
        float raw4 = Math.max(1000  - (1000*indistinguishablesRate4), 0);        
        
        //rawfitness = Math.max(1000  - (1000*indistinguishablesRate), 0); // it should be positive, but just checking.
       
        
        rawfitness = (raw1+raw2+raw3+raw4)/4;
        
        // We finish by taking the ABS of rawfitness.  By the way,
        // in SimpleFitness, fitness values must be set up so that 0 is <= the worst
        // fitness and +infinity is >= the ideal possible fitness.  Our raw fitness
        // value here satisfies this. 
        if (rawfitness < 0) rawfitness = 0;
        if (!(ind2.fitness instanceof SimpleFitness))
            state.output.fatal("Whoa!  It's not a SimpleFitness!!!",null);
        ((SimpleFitness)ind2.fitness).setFitness(state,
            rawfitness, ideal);
        ind2.evaluated = true;
        }
    
    public void describe(final Individual ind, 
        final EvolutionState state, 
        final int subpopulation, 
        final int threadnum,
        final int log,
        final int verbosity)
        {
    	// output to a log file ?
        }
    }
